package com.xiaoye.qbproject.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoye.qbproject.domain.*;
import com.xiaoye.qbproject.mapper.*;
import com.xiaoye.qbproject.redis.RedisCache;
import com.xiaoye.qbproject.redis.RedisConstant;
import com.xiaoye.qbproject.service.BlbcTroopsService;
import com.xiaoye.qbproject.util.StringUtils;
import com.xiaoye.qbproject.vo.TroopsImportVo;
import com.xiaoye.qbproject.vo.TroopsV2ImportVo;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.apache.jena.ontology.*;
import org.apache.jena.rdf.model.ModelFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @description 针对表【BLBC_TROOPS(兵力编程编组)】的数据库操作Service实现
 * @createDate 2024-12-30 11:15:00
 */
@Slf4j
@Service
public class BlbcTroopsServiceImpl extends ServiceImpl<BlbcTroopsMapper, BlbcTroops>
        implements BlbcTroopsService {

    private static final String ns = "http://example.com/zbInfos#";
    @Autowired
    private CountryRegionMapper countryRegionMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private QbWarfareExamplesMapper qbWarfareExamplesMapper;
    @Autowired
    private ZbInfoMapper zbInfoMapper;
    @Autowired
    private BlbcTroopsMapper blbcTroopsMapper;
    @Autowired
    private BlbcWarfareExamplesRelationMapper blbcWarfareExamplesRelationMapper;
    @Autowired
    private BlbcZbRelationMapper blbcZbRelationMapper;

    private static void addTroopsToModel(OntModel ontModel, OntClass blbcTroopsClass, OntProperty hasChildProperty, BlbcTroops troops, String ns) {
        // 为当前troops实例创建个体
        Individual individual = ontModel.createIndividual(ns + troops.getId(), blbcTroopsClass);

        // 如果troops有children，则递归地为它们创建个体，并设置hasChild关系
        if (troops.getChildren() != null) {
            for (BlbcTroops child : troops.getChildren()) {
                OntProperty nameProperty = ontModel.createOntProperty(ns + "troopsName");
                OntProperty summary = ontModel.createOntProperty(ns + "summary");
                OntProperty troopsStyle = ontModel.createOntProperty(ns + "troopsStyle");
                OntProperty militaryService = ontModel.createOntProperty(ns + "militaryService");
                OntProperty domicile = ontModel.createOntProperty(ns + "domicile");
                individual.addProperty(nameProperty, child.getTroopsName());
                individual.addProperty(summary, StringUtils.isBlank(child.getSummary()) ? "" : child.getSummary());
                individual.addProperty(troopsStyle, StringUtils.isBlank(child.getTroopsStyle()) ? "" : child.getTroopsStyle());
                individual.addProperty(militaryService, StringUtils.isBlank(child.getMilitaryService()) ? "" : child.getMilitaryService());
                individual.addProperty(domicile, StringUtils.isBlank(child.getDomicile()) ? "" : child.getDomicile());
                Individual childIndividual = ontModel.createIndividual(ns + child.getId(), blbcTroopsClass);
                ontModel.add(individual, hasChildProperty, childIndividual);
                addTroopsToModel(ontModel, blbcTroopsClass, hasChildProperty, child, ns);
            }
        }
    }

    @Override
    public List<BlbcTroops> buildTree(List<BlbcTroops> list) {
        List<BlbcTroops> returnList = new ArrayList<BlbcTroops>();
        //List<String> tempList = list.stream().map(BlbcTroops::getId).collect(Collectors.toList());
        List<BlbcTroops> parentList = list.stream().filter(e -> StringUtils.isBlank(e.getParentId())).collect(Collectors.toList());
        for (BlbcTroops entity : parentList) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            recursionFn(list, entity);
            returnList.add(entity);
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }
        return returnList;
    }

    /**
     * @param blbcTroops
     * @description: 导入兵力编程编组数据
     * @author: ChenYao
     * @return: void
     * @ceateDate: 2025-01-01 13:52
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importTroops(List<TroopsImportVo> blbcTroops) {
        if (Collections.isEmpty(blbcTroops)) {
            log.info("导入兵力编程编组数据为空");
            return;
        }
        // 查询所有国家数据
        List<CountryRegion> countryRegions = countryRegionMapper.selectList(null);
        // 转成map
        HashMap<String, String> countryMap = new HashMap<>();
        countryRegions.forEach(countryRegion -> countryMap.put(countryRegion.getName(), countryRegion.getId()));
        // 查询所有已有兵力编程编组数据id
        List<String> troopsId = baseMapper.getAllTroopsIds();

        for (TroopsImportVo troopsImportVo : blbcTroops) {
            String troopsName = troopsImportVo.getTroopsName();
            if (StringUtils.isBlank(troopsName) || troopsName.trim().isEmpty()) {
                continue;
            }
            // 在需要的国家里,则继续处理,不在则忽略该数据
            String countryName = troopsImportVo.getCountryName();
            if (!countryMap.containsKey(countryName) && StringUtils.isNotBlank(countryName)) {
                // 如果没有该国家,则新增一个国家数据
                CountryRegion countryRegion = new CountryRegion();
                countryRegion.setName(countryName);
                countryRegionMapper.insert(countryRegion);
                countryMap.put(countryName, countryRegion.getId());
            }
            String countryId = countryMap.get(countryName);

            // 入库数据
            BlbcTroops newBlbcTroops = new BlbcTroops();
            BeanUtils.copyProperties(troopsImportVo, newBlbcTroops);
            newBlbcTroops.setCountryId(countryId);
            newBlbcTroops.setCreateTime(null);
            newBlbcTroops.setUpdateTime(null);
            if (troopsId.contains(newBlbcTroops.getId())) {
                baseMapper.updateById(newBlbcTroops);
            } else {
                baseMapper.insert(newBlbcTroops);
            }
        }

    }

    @Override
    public void delCache() {
        redisCache.deleteObject(RedisConstant.TROOPS_TREE_KEY);
    }

    /**
     * @param countryId
     * @param response
     * @description: 导出兵力编程编组数据
     * @author: ChenYao
     * @return: void
     * @ceateDate: 2025-01-03 16:57
     */
    @Override
    public void exportOwl(String countryId, HttpServletResponse response) {
        List<BlbcTroops> blbcTroops = baseMapper.selectList(Wrappers.<BlbcTroops>lambdaQuery().eq(BlbcTroops::getCountryId, countryId));
        if (Collections.isEmpty(blbcTroops)) {
            log.info("导出兵力编程编组数据为空");
            return;
        }
        // 数据
        List<BlbcTroops> treeList = this.buildTree(blbcTroops);


        // 初始化模型
        OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
        // 设置命名空间
        String ns = "http://example.com/blbcTroops#";
        ontModel.setNsPrefix("blbc", ns);

        // 定义BlbcTroops类
        OntClass blbcTroopsClass = ontModel.createClass(ns + "BlbcTroops");

        // 定义hasChild属性
        OntProperty hasChildProperty = ontModel.createOntProperty(ns + "hasChild");


        // 递归地将treeList数据添加到模型中
        for (BlbcTroops troops : treeList) {
            OntProperty nameProperty = ontModel.createOntProperty(ns + "troopsName");
            OntProperty summary = ontModel.createOntProperty(ns + "summary");
            OntProperty troopsStyle = ontModel.createOntProperty(ns + "troopsStyle");
            OntProperty militaryService = ontModel.createOntProperty(ns + "militaryService");
            OntProperty domicile = ontModel.createOntProperty(ns + "domicile");
            Individual individual = ontModel.createIndividual(ns + troops.getId(), blbcTroopsClass);
            individual.addProperty(nameProperty, troops.getTroopsName());
            individual.addProperty(summary, StringUtils.isBlank(troops.getSummary()) ? "" : troops.getSummary());
            individual.addProperty(troopsStyle, StringUtils.isBlank(troops.getTroopsStyle()) ? "" : troops.getTroopsStyle());
            individual.addProperty(militaryService, StringUtils.isBlank(troops.getMilitaryService()) ? "" : troops.getMilitaryService());
            individual.addProperty(domicile, StringUtils.isBlank(troops.getDomicile()) ? "" : troops.getDomicile());

            addTroopsToModel(ontModel, blbcTroopsClass, hasChildProperty, troops, ns);
        }

        // 将模型导出为OWL文件
        // 将本体写入文件
        try (ServletOutputStream outputStream = response.getOutputStream()
        ) {
            // 使用RDF/XML格式导出
            ontModel.write(outputStream, "RDF/XML-ABBREV");
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTroopsV2(List<TroopsV2ImportVo> troopsV2ImportVos, String countryName) {
        if (Collections.isEmpty(troopsV2ImportVos) || StringUtils.isBlank(countryName)) {
            log.error("导入兵力编程编组数据为空或国家名称为空:{}", countryName);
            return;
        }
        // 查询国家数据
        CountryRegion countryRegion = countryRegionMapper.selectOne(Wrappers.<CountryRegion>lambdaQuery().eq(CountryRegion::getName, countryName).last("limit 1"));
        if (null == countryRegion) {
            countryRegion = new CountryRegion();
            countryRegion.setName(countryName);
            countryRegionMapper.insert(countryRegion);
        }
        // 删除部队名称为空的数据
        baseMapper.delete(Wrappers.<BlbcTroops>lambdaQuery()
                .isNull(BlbcTroops::getTroopsName)
                .or(e -> e.eq(BlbcTroops::getTroopsName, "")
                ));

        // 查询所有部队数据
        List<BlbcTroops> oldTroops = baseMapper.selectList(Wrappers
                .<BlbcTroops>lambdaQuery()
                .eq(BlbcTroops::getCountryId, countryRegion.getId())
                .select(BlbcTroops::getId, BlbcTroops::getParentId, BlbcTroops::getTroopsName)
        );
        // 部队map
        HashMap<String, BlbcTroops> troopsHashMap = new HashMap<>();
        oldTroops.forEach(blbcTroops -> troopsHashMap.put(blbcTroops.getTroopsName(), blbcTroops));

        // 查询所有战例
        List<QbWarfareExamples> qbWarfareExamples = qbWarfareExamplesMapper.selectList(Wrappers
                .<QbWarfareExamples>lambdaQuery()
                .select(QbWarfareExamples::getId, QbWarfareExamples::getName)
        );
        // 战例map
        HashMap<String, String> qbWarfareExamplesMap = new HashMap<>();
        qbWarfareExamples.forEach(qb -> qbWarfareExamplesMap.put(qb.getName(), qb.getId()));

        // 查询所有武器
        List<ZbInfo> zbInfos = zbInfoMapper.selectList(Wrappers.<ZbInfo>lambdaQuery().select(ZbInfo::getId, ZbInfo::getName));
        // 武器map
        HashMap<String, String> zbInfoMap = new HashMap<>();
        zbInfos.forEach(zb -> zbInfoMap.put(zb.getName(), zb.getId()));

        for (TroopsV2ImportVo newTroop : troopsV2ImportVos) {
            // 部队名称
            String troopsName = newTroop.getTroopsName();
            if (StringUtils.isBlank(troopsName) || troopsName.trim().isEmpty()) {
                log.error("导入兵力编程编组 =====空行====== 跳过");
                continue;
            }
            troopsName = troopsName.trim();
            // 入库对象
            BlbcTroops needAddOrEdit = new BlbcTroops();
            BeanUtils.copyProperties(newTroop, needAddOrEdit);
            needAddOrEdit.setTroopsName(troopsName);
            // 设置国家id
            needAddOrEdit.setCountryId(countryRegion.getId());
            String parentName = newTroop.getParentName();
            if (StringUtils.isNotBlank(parentName)) {
                // 获取上级id, 获取不到说明上级id 还没有添加, 添加一条上级id 数据
                BlbcTroops parentTroops = troopsHashMap.get(parentName);
                if (parentTroops == null) {
                    // 添加父国家数据
                    parentTroops = new BlbcTroops();
                    parentTroops.setTroopsName(parentName);
                    parentTroops.setCountryId(countryRegion.getId());
                    // 插入父级数据
                    baseMapper.insert(parentTroops);
                    needAddOrEdit.setParentId(parentTroops.getId());
                }
                // 设置上级id
                needAddOrEdit.setParentId(parentTroops.getId() == null ? null : parentTroops.getId());
                troopsHashMap.put(parentName, parentTroops);
            } else {
                needAddOrEdit.setParentId(null);
            }


            // 存在则设置id, 用于更新数据
            BlbcTroops troops = troopsHashMap.get(troopsName);
            if (troops != null) {
                needAddOrEdit.setId(troops.getId());
                baseMapper.updateById(needAddOrEdit);
            } else {
                baseMapper.insert(needAddOrEdit);
                troopsHashMap.put(troopsName, needAddOrEdit);
            }
            String troopsId = needAddOrEdit.getId();
            // 处理关联数据
            //  处理关联战例
            blbcWarfareExamplesRelationMapper.delete(Wrappers
                    .<BlbcWarfareExamplesRelation>lambdaQuery()
                    .eq(BlbcWarfareExamplesRelation::getBlbcId, troopsId)
            );
            //  添加关联战例数据
            for (String exampleName : newTroop.getTakePartBattleList()) {
                String exampleId = qbWarfareExamplesMap.get(exampleName);
                if (StringUtils.isBlank(exampleId)) {
                    continue;
                   /*// 战例不存在, 添加战例
                    QbWarfareExamples qb = new QbWarfareExamples();
                    qb.setName(exampleName);
                    qbWarfareExamplesMapper.insert(qb);
                    exampleId = qb.getId();
                    qbWarfareExamplesMap.put(exampleName, exampleId);*/
                }
                BlbcWarfareExamplesRelation relation = new BlbcWarfareExamplesRelation();
                relation.setBlbcId(troopsId);
                relation.setWarfareExamplesId(exampleId);
                relation.setText("参与");
                blbcWarfareExamplesRelationMapper.insert(relation);
            }

            // 处理关联武器
            //  删除关联武器数据
            blbcZbRelationMapper.delete(Wrappers.<BlbcZbRelation>lambdaQuery().eq(BlbcZbRelation::getBlbcId, troopsId));
            // 添加关联武器数据
            for (String zbName : newTroop.getZbList()) {
                String zbId = zbInfoMap.get(zbName);
                if (StringUtils.isBlank(zbId)) {
                    continue;
                    // 武器不存在, 添加武器
                   /* ZbInfo zb = new ZbInfo();
                    zb.setName(zbName);
                    zbInfoMapper.insert(zb);
                    zbId = zb.getId();
                    zbInfoMap.put(zbName, zbId);*/
                }
                BlbcZbRelation relation = new BlbcZbRelation();
                relation.setBlbcId(troopsId);
                relation.setZbId(zbId);
                relation.setText("配备");
                blbcZbRelationMapper.insert(relation);
            }

        }
    }

    @Override
    public List<BlbcTroops> tree() {
        // 从缓存中获取树形结构数据
        List<BlbcTroops> tree = redisCache.getCacheObject(RedisConstant.TROOPS_TREE_KEY);
        if (!CollectionUtils.isEmpty(tree)) {
            return tree;
        }
        List<BlbcTroops> list = baseMapper.selectList(Wrappers
                .<BlbcTroops>lambdaQuery().select(BlbcTroops::getId, BlbcTroops::getTroopsName, BlbcTroops::getParentId));
        tree = this.buildTree(list);
        // 将树形结构数据存入缓存中
        redisCache.setCacheObject(RedisConstant.TROOPS_TREE_KEY, tree, 10, TimeUnit.MINUTES);
        return tree;
    }


    private void recursionFn(List<BlbcTroops> list, BlbcTroops t) {
        // 得到子节点列表
        List<BlbcTroops> childList = getChildList(list, t);
        t.setChildren(childList);
        for (BlbcTroops tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<BlbcTroops> getChildList(List<BlbcTroops> list, BlbcTroops t) {
        List<BlbcTroops> tlist = new ArrayList<BlbcTroops>();
        Iterator<BlbcTroops> it = list.iterator();
        while (it.hasNext()) {
            BlbcTroops n = it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().equals(t.getId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<BlbcTroops> list, BlbcTroops t) {
        return getChildList(list, t).size() > 0;
    }
}




